package com.stgy.lease.web.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stgy.lease.common.exception.StgyException;
import com.stgy.lease.common.result.ResultCodeEnum;
import com.stgy.lease.model.domain.*;
import com.stgy.lease.web.admin.dto.AgreementInfoSearchDto;
import com.stgy.lease.web.admin.service.*;
import com.stgy.lease.web.admin.mapper.LeaseAgreementMapper;
import com.stgy.lease.web.admin.vo.AgreementDetailsVo;
import com.stgy.lease.web.admin.vo.AgreementInfoVo;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lingx
 * @description 针对表【lease_agreement(租约信息表)】的数据库操作Service实现
 * @createDate 2024-08-28 11:00:29
 */
@Service
public class LeaseAgreementServiceImpl extends ServiceImpl<LeaseAgreementMapper, LeaseAgreement>
        implements LeaseAgreementService {

    @Autowired
    private PaymentTypeService paymentTypeService;

    @Autowired
    private LeaseTermService leaseTermService;

    @Autowired
    private RoomInfoService roomInfoService;

    @Autowired
    private ApartmentInfoService apartmentInfoService;

    //条件分页查询租约列表
    @Override
    public Page<AgreementInfoVo> pageItem(AgreementInfoSearchDto searchDto) {
        if (searchDto == null) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        //1、先查询LeaseAgreement
        //2、再查询公寓详情apartmentInfo
        //3、查询房间详情roomInfo
        //检索条件需要从上面三张表中获取 所以需要三张表一起
        Page<AgreementInfoVo> page = searchDto.getPage(AgreementInfoVo.class);
        List<AgreementInfoVo> agreemntInfoVoList = baseMapper.selectAgreementInfoVoPage(page, searchDto)
                .stream().map(agreemntInfoVo -> {
                    //4、查询支付方式paymentTpye
                    agreemntInfoVo.setPaymentType(paymentTypeService.getById(agreemntInfoVo.getPaymentTypeId()));
                    //5、查询租期LeaseTerm
                    agreemntInfoVo.setLeaseTerm(leaseTermService.getById(agreemntInfoVo.getLeaseTermId()));
                    return agreemntInfoVo;
                }).collect(Collectors.toList());

        page.setRecords(agreemntInfoVoList);
        return page;
    }

    //根据id查询租约详情
    @Override
    public AgreementDetailsVo getDetailsById(Long id) {
        LeaseAgreement leaseAgreement = this.getById(id);
        if (ObjectUtils.isEmpty(leaseAgreement)) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        AgreementDetailsVo agreementDetailsVo = new AgreementDetailsVo();
        BeanUtils.copyProperties(leaseAgreement, agreementDetailsVo);
        LeaseTerm leaseTerm = leaseTermService.getById(leaseAgreement.getLeaseTermId());
        agreementDetailsVo.setLeaseTerm(leaseTerm);
        PaymentType paymentType = paymentTypeService.getById(leaseAgreement.getPaymentTypeId());
        agreementDetailsVo.setPaymentType(paymentType);
        ApartmentInfo apartmentInfo = apartmentInfoService.getById(leaseAgreement.getApartmentId());
        agreementDetailsVo.setApartmentInfo(apartmentInfo);
        RoomInfo roomInfo = roomInfoService.getById(leaseAgreement.getRoomId());
        agreementDetailsVo.setRoomInfo(roomInfo);
        return agreementDetailsVo;
    }

    //新增或更新租约信息
    @Override
    public boolean saveOrUpdateAgreement(LeaseAgreement leaseAgreement) {
        //业务判断：指定房间是否已存在租约，否则不能租
        Long id = leaseAgreement.getId();

        LambdaQueryWrapper<LeaseAgreement> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(LeaseAgreement::getApartmentId, leaseAgreement.getApartmentId());
        wrapper.eq(LeaseAgreement::getRoomId, leaseAgreement.getRoomId());
        //3、4、6状态表示房间状态可租
        //更新时：如果房间存在租约，并且是自己的租约
//        wrapper.in(LeaseAgreement::getStatus, 3, 4, 6);
        wrapper.last("limit 1");
        LeaseAgreement one = this.getOne(wrapper);
        //如果新增，查询不到租约信息 或者 查询到的租约信息状态是3，4,6 可以新增
        //如果更新，查询不到租约信息 或者 查询到的租约信息id等于自己的 可以更新
        //或者 查询到的租约信息id不等于自己的 状态是3，4,6 可以更新
        List<Integer> statusList = Arrays.asList(3, 4, 6);
        //one不为null id不相等 状态不为3,4,6
        if (one != null && !one.getId().equals(id) && !statusList.contains(one.getStatus())) {
            throw new StgyException(ResultCodeEnum.DATA_ERROR);
        }
        return this.saveOrUpdate(leaseAgreement);
    }

    //定时检查租约状态： 更新或删除租约状态
    @Override
    public void checkAgreementStatus() {
        //1、查询所有的租约
        List<LeaseAgreement> list = this.list();
        //2、遍历租约
        /*
            1、如果租约的状态为 1 签约待确认
                需要检查租约最后一次更新的时间 和现在相差的时间 如果超过允许的时间 修改为取消 3
            2、如果租约的状态为 7 续约待确认
                需要检查租约的到期时间和 现在的时间差 如果超过允许的值 修改为退组 6
            3、如果租约的状态的为 2 已签约
                检查租约的到期时间 >=当前的时间 到期 修改状态为 7
            4、如果租约状态为6
                检查租约到期时间 超过允许的时间 逻辑删除
         */
        //状态位1的租约列表
        list.stream()
                .filter(leaseAgreement -> leaseAgreement.getStatus().equals(1))
                .forEach(leaseAgreement -> {
                    //如果待签约的时间超过3天 修改为取消的状态
                    DateTime dateTime = new DateTime(leaseAgreement.getUpdateTime()).plusDays(4)
                            .withTimeAtStartOfDay();
                    //获取当前时间的 时间毫秒数
                    DateTime now = new DateTime().withTimeAtStartOfDay();
                    if (now.isAfter(dateTime)) { //当前时间超过签约时间3天
                        //超过 修改租约的状态为 3、
                        this.update(Wrappers.lambdaUpdate(LeaseAgreement.class)
                                .eq(LeaseAgreement::getId, leaseAgreement.getId())
                                .eq(LeaseAgreement::getStatus, 1)
                                .set(LeaseAgreement::getStatus, 3)
                                .set(LeaseAgreement::getUpdateTime, new Date()));
                    }
                });
        list.stream()
                .filter(leaseAgreement -> leaseAgreement.getStatus().equals(2))
                .forEach(leaseAgreement -> {
                    //如果租期到期 更新为7 等待用户续约
                    DateTime dateTime = new DateTime(leaseAgreement.getLeaseEndDate()).withTimeAtStartOfDay();
                    //获取当前时间的 时间毫秒数
                    DateTime now = new DateTime().withTimeAtStartOfDay();
                    if (dateTime.equals(now) || now.isAfter(dateTime)) {
                        //等于或超过 修改租约的状态为 7
                        this.update(Wrappers.lambdaUpdate(LeaseAgreement.class)
                                .eq(LeaseAgreement::getId, leaseAgreement.getId())
                                .eq(LeaseAgreement::getStatus, 2)
                                .set(LeaseAgreement::getStatus, 7)
                                .set(LeaseAgreement::getUpdateTime, new Date()));
                    }
                });
        list.stream()
                .filter(leaseAgreement -> leaseAgreement.getStatus().equals(7))
                .forEach(leaseAgreement -> {
                    //如果租期到期等待续约的租期 超过3天 更新为6 已退组
                    DateTime dateTime = new DateTime(leaseAgreement.getLeaseEndDate()).plusDays(4).withTimeAtStartOfDay();
                    //获取当前时间的 时间毫秒数
                    DateTime now = new DateTime().withTimeAtStartOfDay();
                    if (now.isAfter(dateTime)) {
                        //等于或超过 修改租约的状态为 6
                        this.update(Wrappers.lambdaUpdate(LeaseAgreement.class)
                                .eq(LeaseAgreement::getId, leaseAgreement.getId())
                                .eq(LeaseAgreement::getStatus, 7)
                                .set(LeaseAgreement::getStatus, 6)
                                .set(LeaseAgreement::getUpdateTime, new Date()));
                    }
                });
        list.stream()
                .filter(leaseAgreement -> leaseAgreement.getStatus().equals(6))
                .forEach(leaseAgreement -> {
                    DateTime dateTime = new DateTime(leaseAgreement.getLeaseEndDate()).plusDays(7).withTimeAtStartOfDay();
                    DateTime now = new DateTime().withTimeAtStartOfDay();
                    if (dateTime.isAfter(now)) {
                        this.removeById(leaseAgreement.getId());
                    }
                });

    }

    //根据id修改租约状态
    @Override
    public boolean updateStatusById(Long id, Integer status) {
        LambdaUpdateWrapper<LeaseAgreement> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LeaseAgreement::getId, id);
        wrapper.set(LeaseAgreement::getStatus, status);
        return this.update(wrapper);
    }
}